/**
 * Copyright 2013 ABSir's Studio
 * 
 * All right reserved
 *
 * Create on 2013-3-7 下午12:17:51
 */
package com.absir.bean.inject;

import java.lang.ref.SoftReference;
import java.lang.reflect.Field;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

import com.absir.bean.inject.value.Bean;
import com.absir.core.kernel.KernelClass;
import com.absir.core.kernel.KernelCollection;
import com.absir.core.kernel.KernelObject;

/**
 * @author absir
 * 
 */
@Bean
public class InjectAdapter {

	/** Static_Names */
	private static List<String> Static_Names = new ArrayList<String>();

	/** Static_Members */
	private static List<Member> Static_Members = new ArrayList<Member>();

	/** Static_Fields */
	private static List<Field> Static_Fields = new ArrayList<Field>();

	/** Static_Methods */
	private static List<Method> Static_Methods = new ArrayList<Method>();

	/** SoftReference_Objects */
	private static List<Object> SoftReference_Objects = new ArrayList<Object>();

	/**
	 * @param field
	 */
	protected static void injectMember(Field field) {
		field.setAccessible(true);
		Static_Members.add(field);
		Static_Fields.add(field);
	}

	/**
	 * @param method
	 */
	protected static void injectMember(Method method) {
		method.setAccessible(true);
		Static_Members.add(method);
		Static_Methods.add(method);
	}

	/**
	 * @param name
	 * @param referent
	 */
	private static <T> void injectNameReferent(String name, T referent) {
		Static_Names.add(name);
		SoftReference_Objects.add(referent);
		KernelClass.declaredSet(InjectAdapter.class, name, new SoftReference<T>(referent));
	}

	/**
	 * 完成静态注入
	 */
	protected static void injectMembers() {
		Field[] declaredFields = KernelCollection.castToArray(Static_Fields, Field.class);
		Method[] declaredMethods = KernelCollection.castToArray(Static_Methods, Method.class);
		injectNameReferent("declaredFields", declaredFields);
		injectNameReferent("declaredMethods", declaredMethods);

		Class<?> cls = KernelClass.forName("java.lang.ClassCache");
		if (cls != null) {
			Object classCache = KernelClass.declaredNew(cls, InjectAdapter.class);
			if (classCache != null) {
				KernelObject.declaredSet(classCache, "declaredFields", declaredFields);
				KernelObject.declaredSet(classCache, "declaredMethods", declaredMethods);
			}

			injectNameReferent("cacheRef", classCache);
		}
	}

	/**
	 * 注入完成销毁
	 */
	protected static void started() {
		for (String name : Static_Names) {
			KernelClass.declaredSet(InjectAdapter.class, name, null);
		}

		Static_Fields = null;
		Static_Methods = null;
		Static_Names = null;
		Static_Members = null;
		SoftReference_Objects = null;
	}
}
